/*
 * This file (Object.java) is protected by the GNU GPL licence (v2). 
 * Please read the license.txt attached for further informations. 
 * 
 */
package org.algoristes.alkwarel.core;

import java.util.Hashtable;

import org.algoristes.alkwarel.utils.Constants;
import org.algoristes.alkwarel.utils.Log;

/**
 * A basic object which can perform an operation using parameters.
 * 
 * @author Xavier Gouchet
 * 
 */
public abstract class Tool implements Constants {

	protected String mName;
	protected long mID;
	protected Hashtable<String, String> mRequirements;
	protected Hashtable<String, Parameter> mParameters;

	/**
	 * Default Constructor, creating an object which will get a unique ID (long)
	 * and a name. The name provided will also be the name used in script to
	 * call this object.
	 * 
	 * @param name
	 *            the UI name of the object created
	 */
	protected Tool(String name) {
		// initialize basic members
		mName = name.toUpperCase();
		mID = getValidID();
		mRequirements = new Hashtable<String, String>();
		mParameters = new Hashtable<String, Parameter>();

		initRequirements();
	}

	/**
	 * 
	 * @return this object's name
	 */
	public final String getName() {
		return mName;
	}

	/**
	 * 
	 * @return this object's ID
	 */
	public final long getID() {
		return mID;
	}

	/**
	 * Overriden function must return a list of required parameters for the
	 * object in the following form : * [param_name, param_type, ...] <br/>
	 * The names will be the one used in script to parameterize the call to this
	 * object.
	 * 
	 * @return a list of requirements names and types
	 */
	public abstract String[] getRequirements();

	/**
	 * Overriden function must return the default value for the given parameter.
	 * 
	 * @param param
	 *            the name of the parameter
	 * @return the default value (as String) for the given parameter
	 */
	public abstract String getDefaultValue(String param);

	/**
	 * Called to set some params before calling this object.
	 * 
	 * @param params
	 *            a list of parameters name and values (must be in the form
	 *            [param_name, param_value, ...]
	 */
	public final void setParameters(String[] params) {
	}

	/**
	 * Fills the requirements Hashtable from the list defined by child classes
	 */
	private final void initRequirements() {
		String[] reqs = getRequirements();

		// nothing to do if there's no requirements
		if ((reqs == null) || (reqs.length == 0))
			return;

		// error if number of string is even
		if (reqs.length % 2 != 0) {
			Log.severe("Using requirements for object " + mName + " (#" + mID
					+ ") with even number of strings");
		}

		// loop on couples (name, type) and fill hashtable
		for (int i = 0; i < reqs.length; i = i + 2) {
			String n = reqs[i];
			String t = reqs[i + 1];
			String v = getDefaultValue(n); 
			mRequirements.put(n, t);
			mParameters.put(n, new Parameter(n, v, t));
		}

	}

	/** Keeps the max ID already given to give new unique ids */
	private static long MAX_ID = 0;

	/**
	 * Returns a valid and unused ID to a new object;
	 * 
	 * @return a unique ID
	 */
	private static final long getValidID() {
		Log.debug("Tool > getValidID > Using new ID : " + MAX_ID);
		long id = MAX_ID;
		++MAX_ID;
		return id;
	}
}
